package io.renren.modules.efinance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.*;
import io.renren.modules.efinance.dao.AccountDao;
import io.renren.modules.efinance.entity.AccountEntity;
import io.renren.modules.efinance.entity.AccountflowEntity;
import io.renren.modules.efinance.entity.BankcardEntity;
import io.renren.modules.efinance.entity.BindcardEntity;
import io.renren.modules.efinance.service.AccountService;
import io.renren.modules.efinance.service.AccountflowService;
import io.renren.modules.efinance.service.BankcardService;
import io.renren.modules.efinance.service.BindcardService;
import io.renren.modules.efinance.vo.*;
import io.renren.modules.sys.entity.SysUserEntity;
import io.renren.modules.sys.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.stream.Collectors;


@Service("accountService")
@Slf4j
public class AccountServiceImpl extends ServiceImpl<AccountDao, AccountEntity> implements AccountService {

    @Autowired
    private SysUserService sysUserService;
    //    @Autowired
    private AccountflowService accountflowService;
    @Autowired
    private BankcardService bankcardService;

    @Autowired
    private BindcardService bindcardService;

    @Lazy
    public AccountServiceImpl(AccountflowService accountflowService) {
        this.accountflowService = accountflowService;
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AccountEntity> iPage = this.page(
                new Query<AccountEntity>().getPage(params),
                new QueryWrapper<AccountEntity>()
                        .eq("account_name", params.get("account_name")));
        List<AccountEntity> records = iPage.getRecords();
        List<AccountVo> vos = records.stream().map(entity -> toVo(entity)).collect(Collectors.toList());
        return new PageUtils(new Page<AccountVo>(iPage.getCurrent(), iPage.getSize(), iPage.getTotal()).setRecords(vos));
    }

    private AccountVo toVo(AccountEntity entity) {
        AccountVo accountVo = new AccountVo();
        accountVo.setAccountName(entity.getAccountName());
        accountVo.setAccountPhone(entity.getAccountPhone());
        accountVo.setAccountBalance(entity.getAccountBalance());
        accountVo.setAccountOpentime(entity.getAccountOpentime());
        accountVo.setAccountStatus(AccountEnum.matchStatus(entity.getAccountStatus()));
        return accountVo;
    }

    @Override
    public BigDecimal selectBalance(String accountName) {
        return null;
    }

    @Autowired
    private AccountDao accountDao;

//    @Override
//    public boolean selectpassword(String accountId, String accountRealname, String password) {
//        Map<String, String> map = accountDao.selectSaltAndPassword(accountId);
//        String salt = map.get("salt");
//        String oldPassword = map.get("account_password");
//        String md5password = PasswordUtil.getMD5Password(password, salt);
//        boolean re = md5password == oldPassword;
//        return re;
//    }

//    @Override
//    public int selectamount(String accountId, String accountRealname) {
//        return accountDao.selectamount(accountId, accountRealname);
//    }


    /**
     * 账户余额减少，别人账户余额增加
     * @param transferVo
     */
    @Override
    @Transactional
    public void transfer(TransferVo transferVo) {
        // 获取当前账户
        AccountEntity fromAccount = baseMapper.selectOne(new QueryWrapper<AccountEntity>()
                .eq("account_name", ShiroUtils.getUserEntity().getUsername()));
        // 获取目标账户
        AccountEntity toAccount = baseMapper.selectOne(new QueryWrapper<AccountEntity>()
                .eq("account_name", transferVo.getTargetAccountName()));
        // 校验
        if(!PasswordUtil.getMD5Password(transferVo.getAccountPassword(),fromAccount.getSalt()).equals(fromAccount.getAccountPassword())){
            throw new RuntimeException("账户密码错误");
        }
        if(transferVo.getAccountflowMoney().compareTo(fromAccount.getAccountBalance())>0){
            throw new RuntimeException("账户余额不足");
        }
        if(toAccount==null){
            throw new RuntimeException("目标账户不存在");
        }
        if(!transferVo.getTargetAccountRealname().equals(toAccount.getAccountRealname())){
            throw new RuntimeException("目标账户名和姓名不一致");
        }
//        BigDecimal expectMoney=fromAccount.get
        // 更新账户
        fromAccount.setAccountBalance(fromAccount.getAccountBalance().subtract(transferVo.getAccountflowMoney()));
        toAccount.setAccountBalance(toAccount.getAccountBalance().add(transferVo.getAccountflowMoney()));
        if(baseMapper.updateById(fromAccount)<=0){
            log.error("转账扣减失败");
            throw new RuntimeException("转账扣减失败");
        }
        if(baseMapper.updateById(toAccount)<=0){
            log.error("转账增加失败");
            throw new RuntimeException("转账增加失败");
        }
        //添加流水信息
        AccountflowEntity accountflowEntity = AccountflowEntity.builder()
                .accountflowTime(new Date())
                .accountflowType("转账")
                .accountflowMoney(transferVo.getAccountflowMoney())
                .accountflowPayeraccount(ShiroUtils.getUserEntity().getUsername())
                .accountflowPayername(ShiroUtils.getUserEntity().getUsername())
                .accountflowPayeeaccount(transferVo.getTargetAccountName())
                .accountflowPayeename(transferVo.getTargetAccountRealname())
                .accountflowRemarks("")
                .accountflowStatus(1)
                .bankcardIdcard("").build();
        accountflowService.save(accountflowEntity);
    }

//    @Override
//    public int recharge(AccountEntity accountEntity) {
//        return this.baseMapper.recharge(accountEntity);
//    }

    // 充值
    @Override
    @Transactional
    public void recharge(RechargeVo rechargeVo) {
        if(!(rechargeVo.getAccountflowMoney().compareTo(new BigDecimal(0))>0)){
            throw new RuntimeException("请输入正确的金额");

        }
        String account_name = ShiroUtils.getUserEntity().getUsername();
        // 取出账号对象
        AccountEntity accountEntity = this.baseMapper.selectOne(new QueryWrapper<AccountEntity>()
                .eq("account_name", account_name));
        // 获取银行卡对象
        BankcardEntity bankcardEntity = bankcardService.getOne(new QueryWrapper<BankcardEntity>()
                .eq("bankcard_idcard", rechargeVo.getBankcardIdcard()));
        // 获取银行卡的绑定状态
        BindcardEntity bindcardEntity = bindcardService.getOne(new QueryWrapper<BindcardEntity>().eq("card_id", rechargeVo.getBankcardIdcard()));
        if(bindcardEntity==null||!account_name.equals(bindcardEntity.getAccountId())){
            throw new RuntimeException("银行卡不存在或你未绑定该银行卡");
        }
        if (!bankcardEntity.getBankcardPassword().equals(rechargeVo.getBankcardPassword())) {
            throw new RuntimeException("银行卡密码错误");
        }
        if (bankcardEntity.getBankcardBalance().compareTo(rechargeVo.getAccountflowMoney()) < 0) {
            throw new RuntimeException("银行卡余额不足");
        }
        //增加账户余额，减少银行卡余额
        accountEntity.setAccountBalance(accountEntity.getAccountBalance().add(rechargeVo.getAccountflowMoney()));
        bankcardEntity.setBankcardBalance(bankcardEntity.getBankcardBalance().subtract(rechargeVo.getAccountflowMoney()));
        //添加流水信息
        AccountflowEntity accountflowEntity = AccountflowEntity.builder()
                .accountflowTime(new Date())
                .accountflowType("充值")
                .accountflowMoney(rechargeVo.getAccountflowMoney())
                .accountflowPayeraccount(account_name)
                .accountflowPayername(account_name)
                .accountflowPayeeaccount(account_name)
                .accountflowPayeename(account_name)
                .accountflowRemarks("")
                .accountflowStatus(1)
                .bankcardIdcard(rechargeVo.getBankcardIdcard()).build();
//        AccountflowEntity accountflowEntity = new AccountflowEntity(null, new Date(),
//                "充值", rechargeVo.getAccountflowMoney(), account_name,
//                accountEntity.getAccountRealname(), account_name, bankcardEntity.getBankcardUsername(), "", 1, "");
        if (baseMapper.updateById(accountEntity) <= 0) {
            log.error("增加账户金额失败");
            throw new RuntimeException("充值失败");
        }
        if (!bankcardService.updateById(bankcardEntity)) {
            log.error("扣减银行卡余额失败");
            throw new RuntimeException("扣减银行卡金额失败");
        }
        //插入流水信息
        accountflowService.save(accountflowEntity);
    }

    @Override
    @Transactional
    public void withdraw(WithdrawVo withdrawVo) {
        if(!(withdrawVo.getAccountflowMoney().compareTo(new BigDecimal(0))>0)){
            throw new RuntimeException("请输入正确的金额");

        }
        String account_name = ShiroUtils.getUserEntity().getUsername();
        //取出账号对象
        AccountEntity accountEntity = this.baseMapper.selectOne(new QueryWrapper<AccountEntity>()
                .eq("account_name", account_name));
        //通过银行卡号获取银行卡对象
        BankcardEntity bankcardEntity = bankcardService.getOne(new QueryWrapper<BankcardEntity>()
                .eq("bankcard_idcard", withdrawVo.getBankcardIdcard()));
        BindcardEntity bindcardEntity = bindcardService.getOne(new QueryWrapper<BindcardEntity>().eq("card_id", withdrawVo.getBankcardIdcard()));
        if(bindcardEntity==null||!account_name.equals(bindcardEntity.getAccountId())){
            throw new RuntimeException("银行卡不存在或你未绑定该银行卡");
        }
        //比对银行卡密码
//        if (bankcardEntity==null||!bankcardEntity.getBankcardPassword().equals(withdrawVo.getBankcardPassword())) {
//            throw new RuntimeException("银行卡不存在或银行卡密码输入错误");
//        }
        String psw = PasswordUtil.getMD5Password(withdrawVo.getBankcardPassword(),accountEntity.getSalt());
        if (bankcardEntity==null||!accountEntity.getAccountPassword().equals(psw)) {
            throw new RuntimeException("银行卡不存在或账户密码输入错误");
        }
        //查看账户余额是否充足
        if (accountEntity.getAccountBalance().compareTo(withdrawVo.getAccountflowMoney()) < 0) {
            throw new RuntimeException("账户余额不足");
        }
        //减少账户余额，添加银行卡余额
        accountEntity.setAccountBalance(accountEntity.getAccountBalance().subtract(withdrawVo.getAccountflowMoney()));
        bankcardEntity.setBankcardBalance(bankcardEntity.getBankcardBalance().add(withdrawVo.getAccountflowMoney()));
        //添加流水信息
        AccountflowEntity accountflowEntity = AccountflowEntity.builder()
                .accountflowTime(new Date())
                .accountflowType("提现")
                .accountflowMoney(withdrawVo.getAccountflowMoney())
                .accountflowPayeraccount(account_name)
                .accountflowPayername(account_name)
                .accountflowPayeeaccount(account_name)
                .accountflowPayeename(account_name)
                .accountflowRemarks("")
                .accountflowStatus(1)
                .bankcardIdcard(withdrawVo.getBankcardIdcard()).build();
//        AccountflowEntity accountflowEntity = new AccountflowEntity(null,new Date(),"提现",money,
//                account_name,bankcardEntity.getBankcardUsername(),account_name,accountEntity.getAccountRealname(),"",1,"");
        if(baseMapper.updateById(accountEntity)<=0){
            log.error("账户提现失败");
            throw new RuntimeException("账户提现失败");
        }
        if(!bankcardService.updateById(bankcardEntity)){
            log.error("提现到银行卡失败");
            throw new RuntimeException("提现到银行卡失败");
        }

        accountflowService.save(accountflowEntity);

    }

    @Override
    @Transactional
    public void insert(AccountEntity entity) {
        checkEntity(entity);
        populateAccount(entity);
        this.baseMapper.insert(entity);
        //TODO  插入系统表
        sysUserService.saveUser(getSysUserEntity(entity));
    }

    private SysUserEntity getSysUserEntity(AccountEntity accountEntity) {
        SysUserEntity sysUser = new SysUserEntity();
        sysUser.setUserId(Long.parseLong(accountEntity.getAccountId()));
        sysUser.setCreateUserId(Long.parseLong(accountEntity.getAccountId()));
        // 使用自定义盐值和MD5加密，保证校验密码才能一致
        sysUser.setSalt(accountEntity.getSalt());
        sysUser.setPassword(accountEntity.getAccountPassword());
        sysUser.setUsername(accountEntity.getAccountName());
        sysUser.setCreateTime(accountEntity.getAccountOpentime());
        sysUser.setEmail(accountEntity.getAccountEmail());
        sysUser.setMobile(accountEntity.getAccountPhone());
        List<Long> roleList = new ArrayList<>();
        roleList.add(1L);
        sysUser.setRoleIdList(roleList);
        sysUser.setStatus(1);
        return sysUser;
    }

    private void populateAccount(AccountEntity entity) {
        //设置生日
        entity.setAccountBirthday(getBirthday(entity.getAccountId()));
        //创建时间
        entity.setAccountOpentime(new Date());
        //初始金额
        entity.setAccountBalance(new BigDecimal("0.00"));
        //状态码
        entity.setAccountStatus(1);
        //密码加密
//        String salt = UUID.randomUUID().toString().toUpperCase();
        String salt = RandomStringUtils.randomAlphanumeric(20);
        entity.setSalt(salt);
        String oldPassword = entity.getAccountPassword();
        String md5Password = PasswordUtil.getMD5Password(oldPassword, salt);
        entity.setAccountPassword(md5Password);
    }

    /**
     * 获取生日
     *
     * @param accountId
     * @return
     */
    private String getBirthday(String accountId) {
        String birthday = null;
        if (accountId.length() == 15) {
            String substring = accountId.substring(6, 12);
            birthday = "19" + substring;
            birthday = toBirthdayString(birthday);
        } else if (accountId.length() == 18) {
            birthday = accountId.substring(6, 14);
            birthday = toBirthdayString(birthday);
        }
        return birthday;
    }

    /**
     * 生日的格式转化
     *
     * @param birthday
     * @return
     */
    private String toBirthdayString(String birthday) {
        String year = birthday.substring(0, 4) + "年";
        String month = birthday.substring(4, 6) + "月";
        String day = birthday.substring(6, 8) + "日";
        birthday = year + month + day;
        return birthday;
    }

    private void checkEntity(AccountEntity entity) {
        AccountEntity one = this.getOne(new QueryWrapper<AccountEntity>().eq("account_name", entity.getAccountName())
                .or().eq("account_id", entity.getAccountId())
                .or().eq("account_phone", entity.getAccountPhone()));

        //如果不存在该用户，进行注册
        if (one != null) {
            if ((entity.getAccountName().equals(one.getAccountName())))
                throw new RuntimeException("用户名已存在");
            if (entity.getAccountId().equals(one.getAccountId()))
                throw new RuntimeException("身份证号已存在");
            if (entity.getAccountPhone().equals(one.getAccountPhone()))
                throw new RuntimeException("手机号已存在");
        }
    }

}
